﻿using System.ComponentModel;
using System.Runtime.Serialization;

using SharpGL.Enumerations;

namespace SharpGL.OpenGLAttributes
{
    [TypeConverter(typeof(System.ComponentModel.ExpandableObjectConverter))]
    [DataContract(/*IsReference = true, */Name = "OpenGLAttributesGroup", Namespace = "SharpGL.SceneGraph")]
    public class OpenGLAttributesGroup : OpenGLAttributes, INotifyPropertyChanged
    {
        #region Private Fields

        [DataMember()]
        private AccumBufferAttributes accumBufferAttributes = new AccumBufferAttributes();
        [DataMember()]
        private ColorBufferAttributes colorBufferAttributes = new ColorBufferAttributes();
        [DataMember()]
        private CurrentAttributes currentAttributes = new CurrentAttributes();
        [DataMember()]
        private DepthBufferAttributes depthBufferAttributes = new DepthBufferAttributes();
        [DataMember()]
        private EnableAttributes enableAttributes = new EnableAttributes();
        [DataMember()]
        private EvalAttributes evalAttributes = new EvalAttributes();
        [DataMember()]
        private FogAttributes fogAttributes = new FogAttributes();
        [DataMember()]
        private HintAttributes hintAttributes = new HintAttributes();
        [DataMember()]
        private LightingAttributes lightingAttributes = new LightingAttributes();
        [DataMember()]
        private LineAttributes lineAttributes = new LineAttributes();
        [DataMember()]
        private ListAttributes listAttributes = new ListAttributes();
        [DataMember()]
        private PixelModeAttributes pixelModeAttributes = new PixelModeAttributes();
        [DataMember()]
        private PointAttributes pointAttributes = new PointAttributes();
        [DataMember()]
        private PolygonAttributes polygonAttributes = new PolygonAttributes();
        [DataMember()]
        private PolygonStippleAttributes polygonStippleAttributes = new PolygonStippleAttributes();
        [DataMember()]
        private ScissorAttributes scissorAttributes = new ScissorAttributes();
        [DataMember()]
        private StencilBufferAttributes stencilBufferAttributes = new StencilBufferAttributes();
        [DataMember()]
        private TextureAttributes textureAttributes = new TextureAttributes();
        [DataMember()]
        private TransformAttributes transformAttributes = new TransformAttributes();
        [DataMember()]
        private ViewportAttributes viewportAttributes = new ViewportAttributes();

        #endregion Private Fields

        #region Private Methods

        private void OnOpenGLAttributesPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            NotifyPropertyChanged(GetType() + "." + sender.GetType() + "." + e.PropertyName);
        }

        #endregion Private Methods

        #region Protected Methods

        protected override void OnDeserialized()
        {
            accumBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            colorBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            currentAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            depthBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            enableAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            evalAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            fogAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            hintAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            lightingAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            lineAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            listAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            pixelModeAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            pointAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            polygonAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            polygonStippleAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            scissorAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            stencilBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            textureAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            transformAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            viewportAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
        }

        #endregion Protected Methods

        #region Public Constructors

        public OpenGLAttributesGroup()
        {
            accumBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            colorBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            currentAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            depthBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            enableAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            evalAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            fogAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            hintAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            lightingAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            lineAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            listAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            pixelModeAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            pointAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            polygonAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            polygonStippleAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            scissorAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            stencilBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            textureAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            transformAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
            viewportAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
        }

        #endregion Public Constructors

        #region Public Methods

        /// <summary>
        /// Returns true if any attributes are set.
        /// </summary>
        /// <returns>True if any attributes are set</returns>
        public override bool AreAnyAttributesSet()
        {
            return accumBufferAttributes.AreAnyAttributesSet() ||
                colorBufferAttributes.AreAnyAttributesSet() ||
                currentAttributes.AreAnyAttributesSet() ||
                depthBufferAttributes.AreAnyAttributesSet() ||
                enableAttributes.AreAnyAttributesSet() ||
                fogAttributes.AreAnyAttributesSet() ||
                lightingAttributes.AreAnyAttributesSet() ||
                lineAttributes.AreAnyAttributesSet() ||
                pointAttributes.AreAnyAttributesSet() ||
                polygonAttributes.AreAnyAttributesSet() ||
                evalAttributes.AreAnyAttributesSet() ||
                hintAttributes.AreAnyAttributesSet() ||
                listAttributes.AreAnyAttributesSet() ||
                pixelModeAttributes.AreAnyAttributesSet() ||
                polygonStippleAttributes.AreAnyAttributesSet() ||
                scissorAttributes.AreAnyAttributesSet() ||
                stencilBufferAttributes.AreAnyAttributesSet() ||
                textureAttributes.AreAnyAttributesSet() ||
                transformAttributes.AreAnyAttributesSet() ||
                viewportAttributes.AreAnyAttributesSet();
        }

        /// <summary>
        /// Reset all attributes to unset state.
        /// </summary>
        public override void ResetAllAttributes()
        {
            accumBufferAttributes.ResetAllAttributes();
            colorBufferAttributes.ResetAllAttributes();
            currentAttributes.ResetAllAttributes();
            depthBufferAttributes.ResetAllAttributes();
            enableAttributes.ResetAllAttributes();
            fogAttributes.ResetAllAttributes();
            lightingAttributes.ResetAllAttributes();
            lineAttributes.ResetAllAttributes();
            pointAttributes.ResetAllAttributes();
            polygonAttributes.ResetAllAttributes();
            evalAttributes.ResetAllAttributes();
            hintAttributes.ResetAllAttributes();
            listAttributes.ResetAllAttributes();
            pixelModeAttributes.ResetAllAttributes();
            polygonStippleAttributes.ResetAllAttributes();
            scissorAttributes.ResetAllAttributes();
            stencilBufferAttributes.ResetAllAttributes();
            textureAttributes.ResetAllAttributes();
            transformAttributes.ResetAllAttributes();
            viewportAttributes.ResetAllAttributes();
        }

        /// <summary>
        /// Sets the attributes.
        /// </summary>
        /// <param name="gl">The OpenGL instance.</param>
        public override void SetAttributes(OpenGL gl)
        {
            //  Set the attributes.
            accumBufferAttributes.SetAttributes(gl);
            colorBufferAttributes.SetAttributes(gl);
            currentAttributes.SetAttributes(gl);
            depthBufferAttributes.SetAttributes(gl);
            enableAttributes.SetAttributes(gl);
            fogAttributes.SetAttributes(gl);
            lightingAttributes.SetAttributes(gl);
            lineAttributes.SetAttributes(gl);
            pointAttributes.SetAttributes(gl);
            polygonAttributes.SetAttributes(gl);
            evalAttributes.SetAttributes(gl);
            hintAttributes.SetAttributes(gl);
            listAttributes.SetAttributes(gl);
            pixelModeAttributes.SetAttributes(gl);
            polygonStippleAttributes.SetAttributes(gl);
            scissorAttributes.SetAttributes(gl);
            stencilBufferAttributes.SetAttributes(gl);
            textureAttributes.SetAttributes(gl);
            transformAttributes.SetAttributes(gl);
            viewportAttributes.SetAttributes(gl);
        }

        #endregion Public Methods

        #region Public Properties

        /// <summary>
        /// Gets the attribute flags.
        /// todo use get only, xmlignore and don't store them - return them on the fly.
        /// </summary>
        public override AttributeMask AttributeFlags
        {
            get
            {
                //  Create a combined mask.
                AttributeMask attributeFlags = AttributeMask.None;
                attributeFlags |= accumBufferAttributes.AreAnyAttributesSet() ? accumBufferAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= colorBufferAttributes.AreAnyAttributesSet() ? colorBufferAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= currentAttributes.AreAnyAttributesSet() ? currentAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= depthBufferAttributes.AreAnyAttributesSet() ? depthBufferAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= enableAttributes.AreAnyAttributesSet() ? enableAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= fogAttributes.AreAnyAttributesSet() ? fogAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= lightingAttributes.AreAnyAttributesSet() ? lightingAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= lineAttributes.AreAnyAttributesSet() ? lineAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= pointAttributes.AreAnyAttributesSet() ? pointAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= polygonAttributes.AreAnyAttributesSet() ? polygonAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= evalAttributes.AreAnyAttributesSet() ? evalAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= hintAttributes.AreAnyAttributesSet() ? hintAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= listAttributes.AreAnyAttributesSet() ? listAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= pixelModeAttributes.AreAnyAttributesSet() ? pixelModeAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= polygonStippleAttributes.AreAnyAttributesSet() ? polygonStippleAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= scissorAttributes.AreAnyAttributesSet() ? scissorAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= stencilBufferAttributes.AreAnyAttributesSet() ? stencilBufferAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= textureAttributes.AreAnyAttributesSet() ? textureAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= transformAttributes.AreAnyAttributesSet() ? transformAttributes.AttributeFlags : AttributeMask.None;
                attributeFlags |= viewportAttributes.AreAnyAttributesSet() ? viewportAttributes.AttributeFlags : AttributeMask.None;

                return attributeFlags;
            }
        }

        /// <summary>
        /// Gets or sets the hint attributes.
        /// </summary>
        /// <value>
        /// The hint attributes.
        /// </value>
        [Description("Hint attributes"), Category("OpenGL Attributes")]
        public HintAttributes HintAttributes
        {
            get { return hintAttributes; }
            set
            {
                if (hintAttributes != value)
                {
                    if (value == null)
                        hintAttributes.ResetAllAttributes();
                    else
                    {
                        hintAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        hintAttributes = value;
                        hintAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("HintAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the list attributes.
        /// </summary>
        /// <value>
        /// The list attributes.
        /// </value>
        [Description("List attributes"), Category("OpenGL Attributes")]
        public ListAttributes ListAttributes
        {
            get { return listAttributes; }
            set
            {
                if (listAttributes != value)
                {
                    if (value == null)
                        listAttributes.ResetAllAttributes();
                    else
                    {
                        listAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        listAttributes = value;
                        listAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("ListAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the pixel mode attributes.
        /// </summary>
        /// <value>
        /// The pixel mode attributes.
        /// </value>
        [Description("Pixel mode attributes"), Category("OpenGL Attributes")]
        public PixelModeAttributes PixelModeAttributes
        {
            get { return pixelModeAttributes; }
            set
            {
                if (pixelModeAttributes != value)
                {
                    if (value == null)
                        pixelModeAttributes.ResetAllAttributes();
                    else
                    {
                        pixelModeAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        pixelModeAttributes = value;
                        pixelModeAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("PixelModeAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the polygon stipple attributes.
        /// </summary>
        /// <value>
        /// The polygon stipple attributes.
        /// </value>
        [Description("Polygon stipple attributes"), Category("OpenGL Attributes")]
        public PolygonStippleAttributes PolygonStippleAttributes
        {
            get { return polygonStippleAttributes; }
            set
            {
                if (polygonStippleAttributes != value)
                {
                    if (value == null)
                        polygonStippleAttributes.ResetAllAttributes();
                    else
                    {
                        polygonStippleAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        polygonStippleAttributes = value;
                        polygonStippleAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("PolygonStippleAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the scissor attributes.
        /// </summary>
        /// <value>
        /// The scissor attributes.
        /// </value>
        [Description("Scissor attributes"), Category("OpenGL Attributes")]
        public ScissorAttributes ScissorAttributes
        {
            get { return scissorAttributes; }
            set
            {
                if (scissorAttributes != value)
                {
                    if (value == null)
                        scissorAttributes.ResetAllAttributes();
                    else
                    {
                        scissorAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        scissorAttributes = value;
                        scissorAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("ScissorAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the stencil buffer attributes.
        /// </summary>
        /// <value>
        /// The stencil buffer attributes.
        /// </value>
        [Description("Stencil buffer attributes"), Category("OpenGL Attributes")]
        public StencilBufferAttributes StencilBufferAttributes
        {
            get { return stencilBufferAttributes; }
            set
            {
                if (stencilBufferAttributes != value)
                {
                    if (value == null)
                        stencilBufferAttributes.ResetAllAttributes();
                    else
                    {
                        stencilBufferAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        stencilBufferAttributes = value;
                        stencilBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("StencilBufferAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the texture attributes.
        /// </summary>
        /// <value>
        /// The texture attributes.
        /// </value>
        [Description("Texture attributes"), Category("OpenGL Attributes")]
        public TextureAttributes TextureAttributes
        {
            get { return textureAttributes; }
            set
            {
                if (textureAttributes != value)
                {
                    if (value == null)
                        textureAttributes.ResetAllAttributes();
                    else
                    {
                        textureAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        textureAttributes = value;
                        textureAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("TextureAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the transform attributes.
        /// </summary>
        /// <value>
        /// The transform attributes.
        /// </value>
        [Description("Transform attributes"), Category("OpenGL Attributes")]
        public TransformAttributes TransformAttributes
        {
            get { return transformAttributes; }
            set
            {
                if (transformAttributes != value)
                {
                    if (value == null)
                        transformAttributes.ResetAllAttributes();
                    else
                    {
                        transformAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        transformAttributes = value;
                        transformAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("TransformAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the viewport attributes.
        /// </summary>
        /// <value>
        /// The viewport attributes.
        /// </value>
        [Description("Viewport attributes"), Category("OpenGL Attributes")]
        public ViewportAttributes ViewportAttributes
        {
            get { return viewportAttributes; }
            set
            {
                if (viewportAttributes != value)
                {
                    if (value == null)
                        viewportAttributes.ResetAllAttributes();
                    else
                    {
                        viewportAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        viewportAttributes = value;
                        viewportAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("ViewportAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the eval attributes.
        /// </summary>
        /// <value>
        /// The eval attributes.
        /// </value>
        [Description("Eval attributes"), Category("OpenGL Attributes")]
        public EvalAttributes EvalAttributes
        {
            get { return evalAttributes; }
            set
            {
                if (evalAttributes != value)
                {
                    if (value == null)
                        evalAttributes.ResetAllAttributes();
                    else
                    {
                        evalAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        evalAttributes = value;
                        evalAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("EvalAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the accum buffer attributes.
        /// </summary>
        /// <value>
        /// The accum buffer attributes.
        /// </value>
        [Description("AccumBuffer attributes"), Category("OpenGL Attributes")]
        public AccumBufferAttributes AccumBufferAttributes
        {
            get { return accumBufferAttributes; }
            set
            {
                if (accumBufferAttributes != value)
                {
                    if (value == null)
                        accumBufferAttributes.ResetAllAttributes();
                    else
                    {
                        accumBufferAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        accumBufferAttributes = value;
                        accumBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("AccumBufferAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the color buffer attributes.
        /// </summary>
        /// <value>
        /// The color buffer attributes.
        /// </value>
        [Description("ColorBuffer attributes"), Category("OpenGL Attributes")]
        public ColorBufferAttributes ColorBufferAttributes
        {
            get { return colorBufferAttributes; }
            set
            {
                if (colorBufferAttributes != value)
                {
                    if (value == null)
                        colorBufferAttributes.ResetAllAttributes();
                    else
                    {
                        colorBufferAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        colorBufferAttributes = value;
                        colorBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("ColorBufferAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the current attributes.
        /// </summary>
        /// <value>
        /// The current buffer.
        /// </value>
        [Description("Current attributes"), Category("OpenGL Attributes")]
        public CurrentAttributes CurrentAttributes
        {
            get { return currentAttributes; }
            set
            {
                if (currentAttributes != value)
                {
                    if (value == null)
                        currentAttributes.ResetAllAttributes();
                    else
                    {
                        currentAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        currentAttributes = value;
                        currentAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("CurrentAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the depth buffer attributes.
        /// </summary>
        /// <value>
        /// The depth buffer attributes.
        /// </value>
        [Description("DepthBuffer attributes"), Category("OpenGL Attributes")]
        public DepthBufferAttributes DepthBufferAttributes
        {
            get { return depthBufferAttributes; }
            set
            {
                if (depthBufferAttributes != value)
                {
                    if (value == null)
                        depthBufferAttributes.ResetAllAttributes();
                    else
                    {
                        depthBufferAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        depthBufferAttributes = value;
                        depthBufferAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("DepthBufferAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets or sets the enable attributes.
        /// </summary>
        /// <value>
        /// The enable attributes.
        /// </value>
        [Description("Enable attributes"), Category("OpenGL Attributes")]
        public EnableAttributes EnableAttributes
        {
            get { return enableAttributes; }
            set
            {
                if (enableAttributes != value)
                {
                    if (value == null)
                        enableAttributes.ResetAllAttributes();
                    else
                    {
                        enableAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        enableAttributes = value;
                        enableAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("EnableAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets the fog attributes.
        /// </summary>
        [Description("Fog attributes"), Category("OpenGL Attributes")]
        public FogAttributes FogAttributes
        {
            get { return fogAttributes; }
            set
            {
                if (fogAttributes != value)
                {
                    if (value == null)
                        fogAttributes.ResetAllAttributes();
                    else
                    {
                        fogAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        fogAttributes = value;
                        fogAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("FogAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets the lighting attributes.
        /// </summary>
        [Description("Lighting attributes"), Category("OpenGL Attributes")]
        public LightingAttributes LightingAttributes
        {
            get { return lightingAttributes; }
            set
            {
                if (lightingAttributes != value)
                {
                    if (value == null)
                        lightingAttributes.ResetAllAttributes();
                    else
                    {
                        lightingAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        lightingAttributes = value;
                        lightingAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("LightingAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets the line attributes.
        /// </summary>
        [Description("Line attributes"), Category("OpenGL Attributes")]
        public LineAttributes LineAttributes
        {
            get { return lineAttributes; }
            set
            {
                if (lineAttributes != value)
                {
                    if (value == null)
                        lineAttributes.ResetAllAttributes();
                    else
                    {
                        lineAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        lineAttributes = value;
                        lineAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("LineAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets the point attributes.
        /// </summary>
        [Description("Point attributes"), Category("OpenGL Attributes")]
        public PointAttributes PointAttributes
        {
            get { return pointAttributes; }
            set
            {
                if (pointAttributes != value)
                {
                    if (value == null)
                        pointAttributes.ResetAllAttributes();
                    else
                    {
                        pointAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        pointAttributes = value;
                        pointAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("PointAttributes");
                    }
                }
            }
        }

        /// <summary>
        /// Gets the polygon attributes.
        /// </summary>
        [Description("Polygon attributes"), Category("OpenGL Attributes")]
        public PolygonAttributes PolygonAttributes
        {
            get { return polygonAttributes; }
            set
            {
                if (polygonAttributes != value)
                {
                    if (value == null)
                        polygonAttributes.ResetAllAttributes();
                    else
                    {
                        polygonAttributes.PropertyChanged -= new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);
                        polygonAttributes = value;
                        polygonAttributes.PropertyChanged += new PropertyChangedEventHandler(OnOpenGLAttributesPropertyChanged);

                        NotifyPropertyChanged("PolygonAttributes");
                    }
                }
            }
        }

        #endregion Public Properties
    }
}
